// Learn cc.Class:
//  - https://docs.cocos.com/creator/manual/en/scripting/class.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

cc.Class({
    extends: cc.Component,
    ctor(){
        this.w = 720;
        this.h = 1080;
        this.level = 3;
        this.curLevel = 0;
        this.stepX = 0;
        this.stepY = 0;
        this.blockData = [];
        this.isMoving = false;
        this.start = false;
        this.blockSprte = null;
        this.sprites = [
            {
                bg: '1_bg',
                img: '1',
                level: 3
            },
            {
                bg: '2_bg',
                img: '2',
                level: 4
            },     
            {
                bg: '3_bg',
                img: '3',
                level: 5
            },    
            {
                bg: '4_bg',
                img: '4',
                level: 5
            },                                    
        ]
    },
    properties: {
        bg: cc.Sprite,
        gameBox: cc.Node,
        block: cc.Prefab,
        curLevelLabel: cc.Label,
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        this.init()
        //绑定点击事件
        this.initEvent();
    },
    //开始下一关
    toNext(){
        this.isMoving = true;
        setTimeout(()=>{
            this.curLevel +=1;
            if(this.curLevel < this.sprites.length){
                this.clearData();
                this.init()
                this.isMoving = false;
            }else{
                console.log('通关啦！')
                this.curLevelLabel.string = '恭喜您通关啦！'
            }
        }, 1000)

    },
    clearData(){
        this.blockData = [];
        this.gameBox.removeAllChildren()
    },
    init(){
        this.level = this.sprites[this.curLevel].level;
        this.stepX = this.w/this.level;
        this.stepY = this.h/this.level;        
        this.loadImg();
        this.curLevelLabel.string = `第${this.curLevel+1}关`;
    },
    loadImg(){
        let cur = this.sprites[this.curLevel];
        console.log(cc.resources)
        //设置背景图
        cc.resources.load(`img/${cur.bg}`, cc.SpriteFrame, (err, spriteFrame)=>{
            this.bg.spriteFrame = spriteFrame;
        });
        //设置拼图
        cc.resources.load(`img/${cur.img}`, cc.SpriteFrame, (err, spriteFrame)=>{
            this.blockSprte = spriteFrame;
            this.initBlock();
            //移除最后一个
            this.removeLast();
            //打乱排序
            this.rndBlock();
        });        
    },
    initBlock(){
        for(let i=0; i<this.level; i++){
            let arr = [];
            for(let j=0; j<this.level; j++){
                arr.push({x: i, y: j, num: i*this.level+j});
                this.createBlock(i, j);
            }
            this.blockData.push(arr);
        }
    },
    removeLast(){
        this.blockData[this.level-1].pop();
        let lastChildren = this.gameBox.children[this.gameBox.children.length-1];
        this.gameBox.removeChild(lastChildren);
    },
    isComplete(){
        let child = this.gameBox.children;
        let complete = child.every(item=>{
            return item.curPos.x == item.targetPos.x && item.curPos.y == item.targetPos.y
        })
        return complete
    },
    initEvent(){
        this.node.on('clickBlock', (node)=>{
            if(this.isMoving || !this.start){
                return false;
            }
            let x = node.curPos.x;
            let y = node.curPos.y;
            let a = {x: x-1, y: y};
            let b = {x: x, y: y-1};
            let c = {x: x+1, y: y};
            let d = {x: x, y: y+1};
            if(!this.findNode(a)){
                this.isMoving = true
                cc.tween(node).by(0.5, {position: cc.v2(-1*this.stepX, 0)}).call(()=>{ 
                    node.curPos = a;
                    this.isMoving = false;
                    if(this.isComplete()){
                        this.toNext();
                    }
                }).start();
                return 
            }
            if(!this.findNode(b)){
                this.isMoving = true
                cc.tween(node).by(0.5, {position: cc.v2(0, this.stepY)}).call(()=>{ 
                    node.curPos = b;
                    this.isMoving = false;
                    if(this.isComplete()){
                        this.toNext();
                    }
                }).start();
                return 
            }
            if(!this.findNode(c)){
                this.isMoving = true
                cc.tween(node).by(0.5, {position: cc.v2(this.stepX, 0)}).call(()=>{ 
                    node.curPos = c;
                    this.isMoving = false;
                    if(this.isComplete()){
                        this.toNext();
                    }
                }).start();
                return 
            }
            if(!this.findNode(d)){
                this.isMoving = true
                cc.tween(node).by(0.5, {position: cc.v2(0, -1*this.stepY)}).call(()=>{ 
                    node.curPos = d;
                    this.isMoving = false ;
                    if(this.isComplete()){
                        this.toNext();
                    }
                }).start();
                return 
            }
        })
    },
    findNode({x, y}){
        if(x == -1 || y == -1 || x == this.level || y == this.level){
            return true;
        }
        let child = this.gameBox.children;
        let res = child.filter(item=>{
            return item.curPos.x == x && item.curPos.y == y
        });
        if(res.length != 0){
            return true;
        }else{
            return false;
        }
    },
    rndBlock(){
        let child = this.gameBox.children;
        let arr = [];
        this.blockData.map(item=>{
            arr = arr.concat(item);
        })
        arr.sort(()=>Math.random()-0.5);
        while(!this.hasAnswer(arr)){
            arr.sort(()=>Math.random()-0.5);
        }

        for(let i=0; i<arr.length; i++){
            child[i].curPos = arr[i];
            let disX = arr[i].x - child[i].targetPos.x;
            let disY = arr[i].y - child[i].targetPos.y;
            cc.tween(child[i]).delay(3).by(0.5, {position: cc.v2(disX*this.stepX, -1*disY*this.stepY)}).call(()=>{this.start = true}).start();
            //child[i].setPosition(cc.v2(arr[i].x*this.stepX, this.stepY*arr[i].y*-1))
        }
    },
    //是否有解
    hasAnswer(arr){
        let n = 0;
        for(let i=0; i<arr.length; i++){
            let cur = arr[i].num;
            for(let j = i+1; j<arr.length; j++){
                let next = arr[j].num;
                if(next < cur){
                    n++;
                }
            }
        }
        if(n%2==0){
            console.log('有解')
            return true;
        }else{
            console.log('无解')
            return false;
        }
    },
    createBlock(x, y){
        let block = cc.instantiate(this.block);
        let imgNode = block.getChildByName('img');
        block.width = this.stepX;
        block.height = this.stepY;
        block.setPosition(cc.v2(x*this.stepX, this.stepY*y*-1))
        imgNode.setPosition(cc.v2(x*this.stepX*-1, this.stepY*y));
        imgNode.getComponent(cc.Sprite).spriteFrame = this.blockSprte;
        //当前位置
        block.curPos = {x: x, y: y};
        //目标位置
        block.targetPos = {x: x, y: y};  
        this.gameBox.addChild(block); 
    },
    start () {

    },

    // update (dt) {},
});
